1. Project Clover database Tue Apr 9 2024 15:48:38 CDT
  2. Package com.alibaba.fastjson.parser

File DefaultJSONParser.java

 
test_0: Feature.AllowSingleQuotes is false
test_0: setter not found, class com.alibaba.json.bvt.parser.Defau...
test_for_issue_1188: setter not found, class com.alibaba.json.bvt.issue_1100.I...
test_notMatch: setter not found, class com.alibaba.json.bvt.parser.deser...
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_2000.I...
test_8: syntax error
test_3: syntax error
test_for_issue: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_strings_: Feature.AllowSingleQuotes is false
test_0: setter not found, class com.alibaba.json.bvt.TestFlase$VO...
test_value2: setter not found, class com.alibaba.json.bvt.parser.JSONL...
test_PreAuthenticatedAuthenticationToken: setter not found, class org.springframework.security.web....
test_4: setter not found, class com.alibaba.json.bvt.parser.JSONS...
test_null: syntax error
test_enums: Feature.AllowSingleQuotes is false
test_1: Feature.AllowSingleQuotes is false
test_utf8: syntax error
test_for_issue: setter not found, class com.alibaba.json.bvtVO.ae.huangli...
test_date: parseLong error, field : value
test_for_issue: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_39: syntax error
test_value: Feature.AllowSingleQuotes is false
test_2: Feature.AllowSingleQuotes is false
test_error_0: Feature.AllowSingleQuotes is false
test_notMatch: setter not found, class com.alibaba.json.bvt.parser.deser...
test_f: syntax error
test_1: Feature.AllowSingleQuotes is false
test_1: syntax error
test_1: Feature.AllowSingleQuotes is false
test_extra: setter not found, class com.alibaba.json.bvt.parser.Redun...
test_0: syntax error
test_e: Feature.AllowSingleQuotes is false
test_for_issue: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_e: Feature.AllowSingleQuotes is false
test_12: syntax error
test_1: syntax error
test_for_maiksagill: setter not found, class com.alibaba.json.bvtVO.Image, pro...
test_feature: setter not found, class com.alibaba.json.bvt.feature.Disa...
test_2: Feature.AllowSingleQuotes is false
test_bigdecimal: Feature.AllowSingleQuotes is false
test_feature: setter not found, class com.alibaba.json.bvt.feature.Disa...
test_2: syntax error
test_feature2: setter not found, class com.alibaba.json.bvt.feature.Disa...
test_1: syntax error
test_2: setter not found, class com.alibaba.json.bvt.parser.JSONS...
test_0: setter not found, class org.springframework.security.oaut...
test_1: Feature.AllowSingleQuotes is false
test_bigdecimal: Feature.AllowSingleQuotes is false
test_0: syntax error
test_f: syntax error
test_4: syntax error
test_for_bug: setter not found, class com.alibaba.json.bvt.parser.bug.B...
test_for_wangran: setter not found, class com.alibaba.json.bvtVO.QueueEntit...
test_notMatch: setter not found, class com.alibaba.json.bvt.parser.deser...
test_singleQuote: syntax error
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_1200.I...
test_feature2: setter not found, class com.alibaba.json.bvt.feature.Disa...
test: setter not found, class cn.com.tx.domain.pagination.Pagin...
test_12: Feature.AllowSingleQuotes is false
test_6: syntax error
test_2: Feature.AllowSingleQuotes is false
test_for_issue: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_1: Feature.AllowSingleQuotes is false
test_for_issue_false: setter not found, class com.alibaba.json.bvt.bug.Issue939...
test_1: Feature.AllowSingleQuotes is false
test_long_list: setter not found, class com.alibaba.json.bvt.parser.bug.B...
test_parseObject_2: setter not found, class com.alibaba.json.bvt.issue_1200.I...
test_map: Feature.AllowSingleQuotes is false
test_13: Feature.AllowSingleQuotes is false
test_bigdecimal: Feature.AllowSingleQuotes is false
test_url: Feature.AllowSingleQuotes is false
test_f: syntax error
test_final: setter not found, class com.alibaba.json.bvt.FinalTest$VO...
test_date_5: Feature.AllowSingleQuotes is false
test_for_issue: Feature.AllowSingleQuotes is false
test_SecurityContextImpl_x: setter not found, class org.springframework.security.auth...
test_for_hsf: setter not found, class com.alibaba.json.bvt.support.hsf....
test_not_match: setter not found, class com.alibaba.json.bvt.parser.Defau...
test_11: syntax error
test_enum: Feature.AllowSingleQuotes is false
test_2: syntax error
test_strings: Feature.AllowSingleQuotes is false
test_47: syntax error
test_for_issue: syntax error
test_1: Feature.AllowSingleQuotes is false
test_1: setter not found, class com.alibaba.json.bvt.parser.Defau...
test_7: syntax error
test_bigdecimal: Feature.AllowSingleQuotes is false
test_utf: syntax error
test_bytes: Feature.AllowSingleQuotes is false
test_special_browsecue: syntax error
test_2: Feature.AllowSingleQuotes is false
test_notMatch: setter not found, class com.alibaba.json.bvt.parser.deser...
test_for_issue_decode: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_0: setter not found, class com.alibaba.json.bvt.parser.Defau...
test_1: syntax error
test_pattern: Feature.AllowSingleQuotes is false
test_time: parse error
test_dup: setter not found, class com.alibaba.json.bvt.parser.deser...
test_for_ludong: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_1300.I...
test_34: syntax error
test_date_7: Feature.AllowSingleQuotes is false
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_1200.I...
test_0: Feature.AllowSingleQuotes is false
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_1500.I...
test_date: Feature.AllowSingleQuotes is false
test_for_bug: syntax error
test_notMatch: setter not found, class com.alibaba.json.bvt.parser.deser...
test_charArray: syntax error
test_for_issue: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_for_issue: setter not found, class org.springframework.security.web....
test_bigdecimal: Feature.AllowSingleQuotes is false
test_9: syntax error
test_deserializeUsing: syntax error
test_0: setter not found, class com.alibaba.json.bvt.parser.deser...
test_parse: Feature.AllowSingleQuotes is false
test_boolean: Feature.AllowSingleQuotes is false
test_notMatch: setter not found, class com.alibaba.json.bvt.parser.deser...
test_for_issue_true: setter not found, class com.alibaba.json.bvt.bug.Issue939...
test_13: syntax error
test_for_wangran: setter not found, class com.alibaba.json.bvtVO.VirtualTop...
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_2300.I...
test_for_issue: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_extraWithType: setter not found, class com.alibaba.json.bvt.parser.Redun...
test_matchField: setter not found, class com.alibaba.json.bvt.parser.JSONL...
test_6: syntax error
test_b: setter not found, class com.alibaba.json.bvt.parser.JSONL...
test_92: syntax error
test_5: syntax error
test_bigdecimal: Feature.AllowSingleQuotes is false
test_generic: Feature.AllowSingleQuotes is false
test_0: setter not found, class com.alibaba.json.bvtVO.DataTransa...
test_f: syntax error
test_2: Feature.AllowSingleQuotes is false
test_1: syntax error
test_8: syntax error
test_e: Feature.AllowSingleQuotes is false
test_enum_2: Feature.AllowSingleQuotes is false
test_7: syntax error
test_for_issue: setter not found, class com.alibaba.json.bvt.issue_1200.I...
test_singleQuote: syntax error
test_singleQuote_vo: syntax error
test_string_2: Feature.AllowSingleQuotes is false
test_2: setter not found, class com.alibaba.json.bvt.parser.JSONS...
test: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_0: setter not found, class com.alibaba.json.bvt.bug.Bug_for_...
test_10: syntax error
test_0: Feature.AllowSingleQuotes is false
test_enum_error: Feature.AllowSingleQuotes is false
test_strings_2: Feature.AllowSingleQuotes is false
test_url: Feature.AllowSingleQuotes is false
test_0: Feature.AllowSingleQuotes is false
test_user: setter not found, class kotlin.ranges.IntRange, property end
test_sqlDate: For input string: "2024-04-10 04:56:30"
 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
23% of files have more coverage

Code metrics

472
947
65
2
1,769
1,452
372
0.39
14.57
32.5
5.72

Classes

Class Line # Actions
DefaultJSONParser 40 945 0% 371 162
0.8906144589.1%
DefaultJSONParser.ResolveTask 1583 2 0% 1 0
1.0100%
 

Contributing tests

This file is covered by 3018 tests. .

Source view

1    /*
2    * Copyright 1999-2019 Alibaba Group.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16    package com.alibaba.fastjson.parser;
17   
18    import static com.alibaba.fastjson.parser.JSONLexer.EOI;
19    import static com.alibaba.fastjson.parser.JSONToken.*;
20   
21    import java.io.Closeable;
22    import java.lang.reflect.ParameterizedType;
23    import java.lang.reflect.Type;
24    import java.lang.reflect.TypeVariable;
25    import java.lang.reflect.WildcardType;
26    import java.math.BigDecimal;
27    import java.math.BigInteger;
28    import java.text.DateFormat;
29    import java.text.SimpleDateFormat;
30    import java.util.*;
31   
32    import com.alibaba.fastjson.*;
33    import com.alibaba.fastjson.parser.deserializer.*;
34    import com.alibaba.fastjson.serializer.*;
35    import com.alibaba.fastjson.util.TypeUtils;
36   
37    /**
38    * @author wenshao[szujobs@hotmail.com]
39    */
 
40    public class DefaultJSONParser implements Closeable {
41   
42    public final Object input;
43    public final SymbolTable symbolTable;
44    protected ParserConfig config;
45   
46    private final static Set<Class<?>> primitiveClasses = new HashSet<Class<?>>();
47   
48    private String dateFormatPattern = JSON.DEFFAULT_DATE_FORMAT;
49    private DateFormat dateFormat;
50   
51    public final JSONLexer lexer;
52   
53    protected ParseContext context;
54   
55    private ParseContext[] contextArray;
56    private int contextArrayIndex = 0;
57   
58    private List<ResolveTask> resolveTaskList;
59   
60    public final static int NONE = 0;
61    public final static int NeedToResolve = 1;
62    public final static int TypeNameRedirect = 2;
63   
64    public int resolveStatus = NONE;
65   
66    private List<ExtraTypeProvider> extraTypeProviders = null;
67    private List<ExtraProcessor> extraProcessors = null;
68    protected FieldTypeResolver fieldTypeResolver = null;
69   
70    private boolean autoTypeEnable;
71    private String[] autoTypeAccept = null;
72   
73    protected transient BeanContext lastBeanContext;
74   
 
75  1 toggle static {
76  1 Class<?>[] classes = new Class[] {
77    boolean.class,
78    byte.class,
79    short.class,
80    int.class,
81    long.class,
82    float.class,
83    double.class,
84   
85    Boolean.class,
86    Byte.class,
87    Short.class,
88    Integer.class,
89    Long.class,
90    Float.class,
91    Double.class,
92   
93    BigInteger.class,
94    BigDecimal.class,
95    String.class
96    };
97   
98  1 for (Class<?> clazz : classes) {
99  17 primitiveClasses.add(clazz);
100    }
101    }
102   
 
103  26 toggle public String getDateFomartPattern() {
104  26 return dateFormatPattern;
105    }
106   
 
107  12 toggle public DateFormat getDateFormat() {
108  12 if (dateFormat == null) {
109  11 Test failure here dateFormat = new SimpleDateFormat(dateFormatPattern, lexer.getLocale());
110  9 dateFormat.setTimeZone(lexer.getTimeZone());
111    }
112  10 return dateFormat;
113    }
114   
 
115  3 toggle public void setDateFormat(String dateFormat) {
116  3 this.dateFormatPattern = dateFormat;
117  3 this.dateFormat = null;
118    }
119   
 
120  1 toggle public void setDateFomrat(DateFormat dateFormat) {
121  1 this.dateFormat = dateFormat;
122    }
123   
 
124  171 toggle public DefaultJSONParser(String input){
125  171 this(input, ParserConfig.getGlobalInstance(), JSON.DEFAULT_PARSER_FEATURE);
126    }
127   
 
128  102 toggle public DefaultJSONParser(final String input, final ParserConfig config){
129  102 this(input, new JSONScanner(input, JSON.DEFAULT_PARSER_FEATURE), config);
130    }
131   
 
132  20056305 toggle public DefaultJSONParser(final String input, final ParserConfig config, int features){
133  20056305 Test failure here this(input, new JSONScanner(input, features), config);
134    }
135   
 
136  17 toggle public DefaultJSONParser(final char[] input, int length, final ParserConfig config, int features){
137  17 this(input, new JSONScanner(input, length, features), config);
138    }
139   
 
140  275 toggle public DefaultJSONParser(final JSONLexer lexer){
141  275 this(lexer, ParserConfig.getGlobalInstance());
142    }
143   
 
144  275 toggle public DefaultJSONParser(final JSONLexer lexer, final ParserConfig config){
145  275 this(null, lexer, config);
146    }
147   
 
148  20056731 toggle public DefaultJSONParser(final Object input, final JSONLexer lexer, final ParserConfig config){
149  20056731 this.lexer = lexer;
150  20056731 this.input = input;
151  20056731 this.config = config;
152  20056731 this.symbolTable = config.symbolTable;
153   
154  20056719 int ch = lexer.getCurrent();
155  20056719 if (ch == '{') {
156  8033601 lexer.next();
157  8033601 ((JSONLexerBase) lexer).token = JSONToken.LBRACE;
158  12023118 } else if (ch == '[') {
159  12000593 lexer.next();
160  12000593 ((JSONLexerBase) lexer).token = JSONToken.LBRACKET;
161    } else {
162  22525 Test failure here lexer.nextToken(); // prime the pump
163    }
164    }
165   
 
166  4073 toggle public SymbolTable getSymbolTable() {
167  4073 return symbolTable;
168    }
169   
 
170  3 toggle public String getInput() {
171  3 if (input instanceof char[]) {
172  1 return new String((char[]) input);
173    }
174  2 return input.toString();
175    }
176   
 
177  5025561 toggle @SuppressWarnings({ "unchecked", "rawtypes" })
178    public final Object parseObject(final Map object, Object fieldName) {
179  5025561 final JSONLexer lexer = this.lexer;
180   
181  5025561 if (lexer.token() == JSONToken.NULL) {
182  3 lexer.nextToken();
183  3 return null;
184    }
185   
186  5025558 if (lexer.token() == JSONToken.RBRACE) {
187  0 lexer.nextToken();
188  0 return object;
189    }
190   
191  5025558 if (lexer.token() == JSONToken.LITERAL_STRING && lexer.stringVal().length() == 0) {
192  1 lexer.nextToken();
193  1 return object;
194    }
195   
196  5025557 if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA) {
197  1 throw new JSONException("syntax error, expect {, actual " + lexer.tokenName() + ", " + lexer.info());
198    }
199   
200  5025556 ParseContext context = this.context;
201  5025556 try {
202  5025556 boolean isJsonObjectMap = object instanceof JSONObject;
203  5025556 Map map = isJsonObjectMap ? ((JSONObject) object).getInnerMap() : object;
204   
205  5025556 boolean setContextFlag = false;
206  5025556 for (;;) {
207  5098927 lexer.skipWhitespace();
208  5098927 char ch = lexer.getCurrent();
209  5098927 if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
210  5098942 while (ch == ',') {
211  27 lexer.next();
212  27 lexer.skipWhitespace();
213  27 ch = lexer.getCurrent();
214    }
215    }
216   
217  5098927 boolean isObjectKey = false;
218  5098927 Object key;
219  5098927 if (ch == '"') {
220  5098408 key = lexer.scanSymbol(symbolTable, '"');
221  5098408 lexer.skipWhitespace();
222  5098408 ch = lexer.getCurrent();
223  5098408 if (ch != ':') {
224  1 throw new JSONException("expect ':' at " + lexer.pos() + ", name " + key);
225    }
226  519 } else if (ch == '}') {
227  317 lexer.next();
228  317 lexer.resetStringPosition();
229  317 lexer.nextToken();
230   
231  317 if (!setContextFlag) {
232  316 if (this.context != null && fieldName == this.context.fieldName && object == this.context.object) {
233  38 context = this.context;
234    } else {
235  278 ParseContext contextR = setContext(object, fieldName);
236  278 if (context == null) {
237  32 context = contextR;
238    }
239  278 setContextFlag = true;
240    }
241    }
242   
243  317 return object;
244  202 } else if (ch == '\'') {
245  54 if (!lexer.isEnabled(Feature.AllowSingleQuotes)) {
246  35 Test failure here throw new JSONException("syntax error");
247    }
248   
249  19 key = lexer.scanSymbol(symbolTable, '\'');
250  19 lexer.skipWhitespace();
251  19 ch = lexer.getCurrent();
252  19 if (ch != ':') {
253  1 throw new JSONException("expect ':' at " + lexer.pos());
254    }
255  148 } else if (ch == EOI) {
256  2 throw new JSONException("syntax error");
257  146 } else if (ch == ',') {
258  1 throw new JSONException("syntax error");
259  145 } else if ((ch >= '0' && ch <= '9') || ch == '-') {
260  42 lexer.resetStringPosition();
261  42 lexer.scanNumber();
262  42 try {
263  42 if (lexer.token() == JSONToken.LITERAL_INT) {
264  40 key = lexer.integerValue();
265    } else {
266  2 key = lexer.decimalValue(true);
267    }
268  40 if (lexer.isEnabled(Feature.NonStringKeyAsString) || isJsonObjectMap) {
269  26 key = key.toString();
270    }
271    } catch (NumberFormatException e) {
272  1 throw new JSONException("parse number key error" + lexer.info());
273    }
274  40 ch = lexer.getCurrent();
275  40 if (ch != ':') {
276  1 throw new JSONException("parse number key error" + lexer.info());
277    }
278  103 } else if (ch == '{' || ch == '[') {
279  38 lexer.nextToken();
280  38 key = parse();
281  38 isObjectKey = true;
282    } else {
283  65 if (!lexer.isEnabled(Feature.AllowUnQuotedFieldNames)) {
284  1 throw new JSONException("syntax error");
285    }
286   
287  64 key = lexer.scanSymbolUnQuoted(symbolTable);
288  63 lexer.skipWhitespace();
289  63 ch = lexer.getCurrent();
290  63 if (ch != ':') {
291  1 throw new JSONException("expect ':' at " + lexer.pos() + ", actual " + ch);
292    }
293    }
294   
295  5098564 if (!isObjectKey) {
296  5098526 lexer.next();
297  5098526 lexer.skipWhitespace();
298    }
299   
300  5098564 ch = lexer.getCurrent();
301   
302  5098564 lexer.resetStringPosition();
303   
304  5098564 if (key == JSON.DEFAULT_TYPE_KEY
305    && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
306  12868 String typeName = lexer.scanSymbol(symbolTable, '"');
307   
308  12868 if (lexer.isEnabled(Feature.IgnoreAutoType)) {
309  16 continue;
310    }
311   
312  12852 Class<?> clazz = null;
313  12852 if (object != null
314    && object.getClass().getName().equals(typeName)) {
315  7 clazz = object.getClass();
316    } else {
317   
318  12845 boolean allDigits = true;
319  12849 for (int i = 0; i < typeName.length(); ++i) {
320  12848 char c = typeName.charAt(i);
321  12848 if (c < '0' || c > '9') {
322  12844 allDigits = false;
323  12844 break;
324    }
325    }
326   
327  12845 if (!allDigits) {
328  12844 clazz = config.checkAutoType(typeName, null, lexer.getFeatures());
329    }
330    }
331   
332  12834 if (clazz == null) {
333  12 map.put(JSON.DEFAULT_TYPE_KEY, typeName);
334  12 continue;
335    }
336   
337  12822 lexer.nextToken(JSONToken.COMMA);
338  12822 if (lexer.token() == JSONToken.RBRACE) {
339  450 lexer.nextToken(JSONToken.COMMA);
340  450 try {
341  450 Object instance = null;
342  450 ObjectDeserializer deserializer = this.config.getDeserializer(clazz);
343  450 if (deserializer instanceof JavaBeanDeserializer) {
344  428 instance = TypeUtils.cast(object, clazz, this.config);
345    }
346   
347  450 if (instance == null) {
348  22 if (clazz == Cloneable.class) {
349  1 instance = new HashMap();
350  21 } else if ("java.util.Collections$EmptyMap".equals(typeName)) {
351  1 instance = Collections.emptyMap();
352  20 } else if ("java.util.Collections$UnmodifiableMap".equals(typeName)) {
353  1 instance = Collections.unmodifiableMap(new HashMap());
354    } else {
355  19 instance = clazz.newInstance();
356    }
357    }
358   
359  450 return instance;
360    } catch (Exception e) {
361  0 throw new JSONException("create instance error", e);
362    }
363    }
364   
365  12372 this.setResolveStatus(TypeNameRedirect);
366   
367  12372 if (this.context != null
368    && fieldName != null
369    && !(fieldName instanceof Integer)
370    && !(this.context.fieldName instanceof Integer)) {
371  4074 this.popContext();
372    }
373   
374  12372 if (object.size() > 0) {
375  3155 Object newObj = TypeUtils.cast(object, clazz, this.config);
376  3155 this.setResolveStatus(NONE);
377  3155 this.parseObject(newObj);
378  3155 return newObj;
379    }
380   
381  9217 ObjectDeserializer deserializer = config.getDeserializer(clazz);
382  9217 Class deserClass = deserializer.getClass();
383  9217 if (JavaBeanDeserializer.class.isAssignableFrom(deserClass)
384    && deserClass != JavaBeanDeserializer.class
385    && deserClass != ThrowableDeserializer.class) {
386  262 this.setResolveStatus(NONE);
387  8955 } else if (deserializer instanceof MapDeserializer) {
388  38 this.setResolveStatus(NONE);
389    }
390  9217 Test failure here Object obj = deserializer.deserialze(this, clazz, fieldName);
391  9209 return obj;
392    }
393   
394  5085696 if (key == "$ref"
395    && context != null
396    && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
397  3279 lexer.nextToken(JSONToken.LITERAL_STRING);
398  3279 if (lexer.token() == JSONToken.LITERAL_STRING) {
399  3278 String ref = lexer.stringVal();
400  3278 lexer.nextToken(JSONToken.RBRACE);
401   
402  3278 if (lexer.token() == JSONToken.COMMA) {
403  0 map.put(key, ref);
404  0 continue;
405    }
406   
407  3278 Object refValue = null;
408  3278 if ("@".equals(ref)) {
409  5 if (this.context != null) {
410  5 ParseContext thisContext = this.context;
411  5 Object thisObj = thisContext.object;
412  5 if (thisObj instanceof Object[] || thisObj instanceof Collection<?>) {
413  2 refValue = thisObj;
414  3 } else if (thisContext.parent != null) {
415  1 refValue = thisContext.parent.object;
416    }
417    }
418  3273 } else if ("..".equals(ref)) {
419  4 if (context.object != null) {
420  3 refValue = context.object;
421    } else {
422  1 addResolveTask(new ResolveTask(context, ref));
423  1 setResolveStatus(DefaultJSONParser.NeedToResolve);
424    }
425  3269 } else if ("$".equals(ref)) {
426  6 ParseContext rootContext = context;
427  8 while (rootContext.parent != null) {
428  2 rootContext = rootContext.parent;
429    }
430   
431  6 if (rootContext.object != null) {
432  5 refValue = rootContext.object;
433    } else {
434  1 addResolveTask(new ResolveTask(rootContext, ref));
435  1 setResolveStatus(DefaultJSONParser.NeedToResolve);
436    }
437    } else {
438  3263 addResolveTask(new ResolveTask(context, ref));
439  3263 setResolveStatus(DefaultJSONParser.NeedToResolve);
440    }
441   
442  3278 if (lexer.token() != JSONToken.RBRACE) {
443  1 throw new JSONException("syntax error, " + lexer.info());
444    }
445  3277 lexer.nextToken(JSONToken.COMMA);
446   
447  3277 return refValue;
448    } else {
449  1 throw new JSONException("illegal ref, " + JSONToken.name(lexer.token()));
450    }
451    }
452   
453  5082417 if (!setContextFlag) {
454  5018649 if (this.context != null && fieldName == this.context.fieldName && object == this.context.object) {
455  7007 context = this.context;
456    } else {
457  5011642 ParseContext contextR = setContext(object, fieldName);
458  5011642 if (context == null) {
459  5004088 context = contextR;
460    }
461  5011642 setContextFlag = true;
462    }
463    }
464   
465  5082417 if (object.getClass() == JSONObject.class) {
466  5082303 if (key == null) {
467  1 key = "null";
468    }
469    }
470   
471  5082417 Object value;
472  5082417 if (ch == '"') {
473  27988 lexer.scanString();
474  27984 String strValue = lexer.stringVal();
475  27984 value = strValue;
476   
477  27984 if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
478  24818 JSONScanner iso8601Lexer = new JSONScanner(strValue);
479  24815 Test failure here if (iso8601Lexer.scanISO8601DateIfMatch()) {
480  2 value = iso8601Lexer.getCalendar().getTime();
481    }
482  24815 iso8601Lexer.close();
483    }
484   
485  27981 map.put(key, value);
486  5054429 } else if (ch >= '0' && ch <= '9' || ch == '-') {
487  5032351 lexer.scanNumber();
488  5032351 if (lexer.token() == JSONToken.LITERAL_INT) {
489  1027448 value = lexer.integerValue();
490    } else {
491  4004903 value = lexer.decimalValue(lexer.isEnabled(Feature.UseBigDecimal));
492    }
493   
494  5032345 map.put(key, value);
495  22078 } else if (ch == '[') { // 减少嵌套,兼容android
496  9773 lexer.nextToken();
497   
498  9773 JSONArray list = new JSONArray();
499   
500  9773 final boolean parentIsArray = fieldName != null && fieldName.getClass() == Integer.class;
501    // if (!parentIsArray) {
502    // this.setContext(context);
503    // }
504  9773 if (fieldName == null) {
505  4162 this.setContext(context);
506    }
507   
508  9773 this.parseArray(list, key);
509   
510  9773 if (lexer.isEnabled(Feature.UseObjectArray)) {
511  1 value = list.toArray();
512    } else {
513  9772 value = list;
514    }
515  9773 map.put(key, value);
516   
517  9773 if (lexer.token() == JSONToken.RBRACE) {
518  304 lexer.nextToken();
519  304 return object;
520  9469 } else if (lexer.token() == JSONToken.COMMA) {
521  9468 continue;
522    } else {
523  1 throw new JSONException("syntax error");
524    }
525  12305 } else if (ch == '{') { // 减少嵌套,兼容 Android
526  9817 lexer.nextToken();
527   
528  9817 final boolean parentIsArray = fieldName != null && fieldName.getClass() == Integer.class;
529   
530  9817 Map input;
531  9817 if (lexer.isEnabled(Feature.CustomMapDeserializer)) {
532  1 MapDeserializer mapDeserializer = (MapDeserializer) config.getDeserializer(Map.class);
533   
534   
535  1 input = (lexer.getFeatures() & Feature.OrderedField.mask) != 0
536    ? mapDeserializer.createMap(Map.class, lexer.getFeatures())
537    : mapDeserializer.createMap(Map.class);
538    } else {
539  9816 input = new JSONObject(lexer.isEnabled(Feature.OrderedField));
540    }
541  9817 ParseContext ctxLocal = null;
542   
543  9817 if (!parentIsArray) {
544  6282 ctxLocal = setContext(context, input, key);
545    }
546   
547  9817 Object obj = null;
548  9817 boolean objParsed = false;
549  9817 if (fieldTypeResolver != null) {
550  2 String resolveFieldName = key != null ? key.toString() : null;
551  2 Type fieldType = fieldTypeResolver.resolve(object, resolveFieldName);
552  2 if (fieldType != null) {
553  2 ObjectDeserializer fieldDeser = config.getDeserializer(fieldType);
554  2 obj = fieldDeser.deserialze(this, fieldType, key);
555  2 objParsed = true;
556    }
557    }
558  9817 if (!objParsed) {
559  9815 obj = this.parseObject(input, key);
560    }
561   
562  9816 if (ctxLocal != null && input != obj) {
563  5301 ctxLocal.object = object;
564    }
565   
566  9816 if (key != null) {
567  9815 checkMapResolve(object, key.toString());
568    }
569   
570  9816 map.put(key, obj);
571   
572  9816 if (parentIsArray) {
573    //setContext(context, obj, key);
574  3534 setContext(obj, key);
575    }
576   
577  9816 if (lexer.token() == JSONToken.RBRACE) {
578  1109 lexer.nextToken();
579   
580  1109 setContext(context);
581  1109 return object;
582  8707 } else if (lexer.token() == JSONToken.COMMA) {
583  8705 if (parentIsArray) {
584  3483 this.popContext();
585    } else {
586  5222 this.setContext(context);
587    }
588  8705 continue;
589    } else {
590  2 throw new JSONException("syntax error, " + lexer.tokenName());
591    }
592    } else {
593  2488 Test failure here lexer.nextToken();
594  2477 value = parse();
595   
596  2474 map.put(key, value);
597   
598  2474 if (lexer.token() == JSONToken.RBRACE) {
599  218 lexer.nextToken();
600  218 return object;
601  2256 } else if (lexer.token() == JSONToken.COMMA) {
602  2254 continue;
603    } else {
604  2 throw new JSONException("syntax error, position at " + lexer.pos() + ", name " + key);
605    }
606    }
607   
608  5060326 lexer.skipWhitespace();
609  5060325 ch = lexer.getCurrent();
610  5060325 if (ch == ',') {
611  52916 lexer.next();
612  52916 continue;
613  5007409 } else if (ch == '}') {
614  5007404 lexer.next();
615  5007404 lexer.resetStringPosition();
616  5007404 lexer.nextToken();
617   
618    // this.setContext(object, fieldName);
619  5007404 this.setContext(value, key);
620   
621  5007404 return object;
622    } else {
623  5 throw new JSONException("syntax error, position at " + lexer.pos() + ", name " + key);
624    }
625   
626    }
627    } finally {
628  5025556 this.setContext(context);
629    }
630   
631    }
632   
 
633  10095052 toggle public ParserConfig getConfig() {
634  10095052 return config;
635    }
636   
 
637  1 toggle public void setConfig(ParserConfig config) {
638  1 this.config = config;
639    }
640   
641    // compatible
 
642  249 toggle @SuppressWarnings("unchecked")
643    public <T> T parseObject(Class<T> clazz) {
644  249 Test failure here return (T) parseObject(clazz, null);
645    }
646   
 
647  10000069 toggle public <T> T parseObject(Type type) {
648  10000069 return parseObject(type, null);
649    }
650   
 
651  25031432 toggle @SuppressWarnings("unchecked")
652    public <T> T parseObject(Type type, Object fieldName) {
653  25031432 int token = lexer.token();
654  25031432 if (token == JSONToken.NULL) {
655  46 lexer.nextToken();
656  46 return null;
657    }
658   
659  25031386 if (token == JSONToken.LITERAL_STRING) {
660  2242 if (type == byte[].class) {
661  8 byte[] bytes = lexer.bytesValue();
662  8 lexer.nextToken();
663  8 return (T) bytes;
664    }
665   
666  2234 if (type == char[].class) {
667  1 String strVal = lexer.stringVal();
668  1 lexer.nextToken();
669  1 return (T) strVal.toCharArray();
670    }
671    }
672   
673  25031377 ObjectDeserializer deserializer = config.getDeserializer(type);
674   
675  25031374 try {
676  25031374 if (deserializer.getClass() == JavaBeanDeserializer.class) {
677  9306 if (lexer.token()!= JSONToken.LBRACE && lexer.token()!=JSONToken.LBRACKET) {
678  0 throw new JSONException("syntax error,except start with { or [,but actually start with "+ lexer.tokenName());
679    }
680  9306 Test failure here return (T) ((JavaBeanDeserializer) deserializer).deserialze(this, type, fieldName, 0);
681    } else {
682  25022068 Test failure here return (T) deserializer.deserialze(this, type, fieldName);
683    }
684    } catch (JSONException e) {
685  419 throw e;
686    } catch (Throwable e) {
687  32 Test failure here throw new JSONException(e.getMessage(), e);
688    }
689    }
690   
 
691  25 toggle public <T> List<T> parseArray(Class<T> clazz) {
692  25 List<T> array = new ArrayList<T>();
693  25 Test failure here parseArray(clazz, array);
694  17 return array;
695    }
696   
 
697  69 toggle public void parseArray(Class<?> clazz, @SuppressWarnings("rawtypes") Collection array) {
698  69 Test failure here parseArray((Type) clazz, array);
699    }
700   
 
701  87 toggle @SuppressWarnings("rawtypes")
702    public void parseArray(Type type, Collection array) {
703  87 Test failure here parseArray(type, array, null);
704    }
705   
 
706  10004383 toggle @SuppressWarnings({ "unchecked", "rawtypes" })
707    public void parseArray(Type type, Collection array, Object fieldName) {
708  10004383 int token = lexer.token();
709  10004383 if (token == JSONToken.SET || token == JSONToken.TREE_SET) {
710  3 lexer.nextToken();
711  3 token = lexer.token();
712    }
713   
714  10004383 if (token != JSONToken.LBRACKET) {
715  16 throw new JSONException("expect '[', but " + JSONToken.name(token) + ", " + lexer.info());
716    }
717   
718  10004367 ObjectDeserializer deserializer = null;
719  10004367 if (int.class == type) {
720  17 deserializer = IntegerCodec.instance;
721  17 lexer.nextToken(JSONToken.LITERAL_INT);
722  10004350 } else if (String.class == type) {
723  2033 deserializer = StringCodec.instance;
724  2033 Test failure here lexer.nextToken(JSONToken.LITERAL_STRING);
725    } else {
726  10002317 deserializer = config.getDeserializer(type);
727  10002317 Test failure here lexer.nextToken(deserializer.getFastMatchToken());
728    }
729   
730  10004361 ParseContext context = this.context;
731  10004361 this.setContext(array, fieldName);
732  10004361 try {
733  10004361 for (int i = 0;; ++i) {
734  20078742 if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
735  20078742 while (lexer.token() == JSONToken.COMMA) {
736  11 lexer.nextToken();
737  11 continue;
738    }
739    }
740   
741  20078742 if (lexer.token() == JSONToken.RBRACKET) {
742  10004334 break;
743    }
744   
745  10074408 if (int.class == type) {
746  172 Object val = IntegerCodec.instance.deserialze(this, null, null);
747  172 array.add(val);
748  10074236 } else if (String.class == type) {
749  4024 String value;
750  4024 if (lexer.token() == JSONToken.LITERAL_STRING) {
751  3995 value = lexer.stringVal();
752  3995 lexer.nextToken(JSONToken.COMMA);
753    } else {
754  29 Object obj = this.parse();
755  17 if (obj == null) {
756  6 value = null;
757    } else {
758  11 value = obj.toString();
759    }
760    }
761   
762  4012 array.add(value);
763    } else {
764  10070212 Object val;
765  10070212 if (lexer.token() == JSONToken.NULL) {
766  263 lexer.nextToken();
767  263 val = null;
768    } else {
769  10069949 Test failure here val = deserializer.deserialze(this, type, i);
770    }
771  10070197 array.add(val);
772  10070197 checkListResolve(array);
773    }
774   
775  10074381 if (lexer.token() == JSONToken.COMMA) {
776  70075 lexer.nextToken(deserializer.getFastMatchToken());
777  70075 continue;
778    }
779    }
780    } finally {
781  10004361 this.setContext(context);
782    }
783   
784  10004334 lexer.nextToken(JSONToken.COMMA);
785    }
786   
 
787  50 toggle public Object[] parseArray(Type[] types) {
788  50 if (lexer.token() == JSONToken.NULL) {
789  1 lexer.nextToken(JSONToken.COMMA);
790  1 return null;
791    }
792   
793  49 if (lexer.token() != JSONToken.LBRACKET) {
794  4 throw new JSONException("syntax error : " + lexer.tokenName());
795    }
796   
797  45 Object[] list = new Object[types.length];
798  45 if (types.length == 0) {
799  2 lexer.nextToken(JSONToken.RBRACKET);
800   
801  1 if (lexer.token() != JSONToken.RBRACKET) {
802  0 throw new JSONException("syntax error");
803    }
804   
805  1 lexer.nextToken(JSONToken.COMMA);
806  1 return new Object[0];
807    }
808   
809  43 Test failure here lexer.nextToken(JSONToken.LITERAL_INT);
810   
811  72 for (int i = 0; i < types.length; ++i) {
812  70 Object value;
813   
814  70 if (lexer.token() == JSONToken.NULL) {
815  5 value = null;
816  5 lexer.nextToken(JSONToken.COMMA);
817    } else {
818  65 Type type = types[i];
819  65 if (type == int.class || type == Integer.class) {
820  17 if (lexer.token() == JSONToken.LITERAL_INT) {
821  17 value = Integer.valueOf(lexer.intValue());
822  17 lexer.nextToken(JSONToken.COMMA);
823    } else {
824  0 value = this.parse();
825  0 value = TypeUtils.cast(value, type, config);
826    }
827  48 } else if (type == String.class) {
828  12 if (lexer.token() == JSONToken.LITERAL_STRING) {
829  10 value = lexer.stringVal();
830  10 lexer.nextToken(JSONToken.COMMA);
831    } else {
832  2 value = this.parse();
833  2 value = TypeUtils.cast(value, type, config);
834    }
835    } else {
836  36 boolean isArray = false;
837  36 Class<?> componentType = null;
838  36 if (i == types.length - 1) {
839  30 if (type instanceof Class) {
840  25 Class<?> clazz = (Class<?>) type;
841    //如果最后一个type是字节数组,且当前token为字符串类型,不应该当作可变长参数进行处理
842    //而是作为一个整体的Base64字符串进行反序列化
843  25 if (!((clazz == byte[].class || clazz == char[].class) && lexer.token() == LITERAL_STRING)) {
844  23 isArray = clazz.isArray();
845  23 componentType = clazz.getComponentType();
846    }
847    }
848    }
849   
850    // support varArgs
851  36 if (isArray && lexer.token() != JSONToken.LBRACKET) {
852  6 List<Object> varList = new ArrayList<Object>();
853   
854  6 ObjectDeserializer deserializer = config.getDeserializer(componentType);
855  6 int fastMatch = deserializer.getFastMatchToken();
856   
857  6 if (lexer.token() != JSONToken.RBRACKET) {
858  4 for (;;) {
859  12 Object item = deserializer.deserialze(this, type, null);
860  12 varList.add(item);
861   
862  12 if (lexer.token() == JSONToken.COMMA) {
863  8 lexer.nextToken(fastMatch);
864  4 } else if (lexer.token() == JSONToken.RBRACKET) {
865  3 break;
866    } else {
867  1 throw new JSONException("syntax error :" + JSONToken.name(lexer.token()));
868    }
869    }
870    }
871   
872  5 value = TypeUtils.cast(varList, type, config);
873    } else {
874  30 ObjectDeserializer deserializer = config.getDeserializer(type);
875  30 Test failure here value = deserializer.deserialze(this, type, i);
876    }
877    }
878    }
879  68 list[i] = value;
880   
881  68 if (lexer.token() == JSONToken.RBRACKET) {
882  36 break;
883    }
884   
885  32 if (lexer.token() != JSONToken.COMMA) {
886  0 throw new JSONException("syntax error :" + JSONToken.name(lexer.token()));
887    }
888   
889  32 if (i == types.length - 1) {
890  2 lexer.nextToken(JSONToken.RBRACKET);
891    } else {
892  30 lexer.nextToken(JSONToken.LITERAL_INT);
893    }
894    }
895   
896  38 if (lexer.token() != JSONToken.RBRACKET) {
897  2 throw new JSONException("syntax error");
898    }
899   
900  36 lexer.nextToken(JSONToken.COMMA);
901   
902  36 return list;
903    }
904   
 
905  3175 toggle public void parseObject(Object object) {
906  3175 Class<?> clazz = object.getClass();
907  3175 JavaBeanDeserializer beanDeser = null;
908  3175 ObjectDeserializer deserializer = config.getDeserializer(clazz);
909  3175 if (deserializer instanceof JavaBeanDeserializer) {
910  3175 beanDeser = (JavaBeanDeserializer) deserializer;
911    }
912   
913  3175 if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA) {
914  1 throw new JSONException("syntax error, expect {, actual " + lexer.tokenName());
915    }
916   
917  3174 for (;;) {
918    // lexer.scanSymbol
919  13895 Test failure here String key = lexer.scanSymbol(symbolTable);
920   
921  13894 if (key == null) {
922  19 if (lexer.token() == JSONToken.RBRACE) {
923  2 lexer.nextToken(JSONToken.COMMA);
924  2 break;
925    }
926  17 if (lexer.token() == JSONToken.COMMA) {
927  17 if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
928  16 continue;
929    }
930    }
931    }
932   
933  13876 FieldDeserializer fieldDeser = null;
934  13876 if (beanDeser != null) {
935  13876 fieldDeser = beanDeser.getFieldDeserializer(key);
936    }
937   
938  13876 if (fieldDeser == null) {
939  6 if (!lexer.isEnabled(Feature.IgnoreNotMatch)) {
940  5 Test failure here throw new JSONException("setter not found, class " + clazz.getName() + ", property " + key);
941    }
942   
943  1 lexer.nextTokenWithColon();
944  1 parse(); // skip
945   
946  1 if (lexer.token() == JSONToken.RBRACE) {
947  0 lexer.nextToken();
948  0 return;
949    }
950   
951  1 continue;
952    } else {
953  13870 Class<?> fieldClass = fieldDeser.fieldInfo.fieldClass;
954  13870 Type fieldType = fieldDeser.fieldInfo.fieldType;
955  13870 Object fieldValue;
956  13870 if (fieldClass == int.class) {
957  4645 lexer.nextTokenWithColon(JSONToken.LITERAL_INT);
958  4645 fieldValue = IntegerCodec.instance.deserialze(this, fieldType, null);
959  9225 } else if (fieldClass == String.class) {
960  7 lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
961  7 fieldValue = StringCodec.deserialze(this);
962  9218 } else if (fieldClass == long.class) {
963  1 lexer.nextTokenWithColon(JSONToken.LITERAL_INT);
964  1 fieldValue = LongCodec.instance.deserialze(this, fieldType, null);
965    } else {
966  9217 ObjectDeserializer fieldValueDeserializer = config.getDeserializer(fieldClass, fieldType);
967   
968  9217 lexer.nextTokenWithColon(fieldValueDeserializer.getFastMatchToken());
969  9217 Test failure here fieldValue = fieldValueDeserializer.deserialze(this, fieldType, null);
970    }
971   
972  13869 fieldDeser.setValue(object, fieldValue);
973    }
974   
975  13868 if (lexer.token() == JSONToken.COMMA) {
976  10704 continue;
977    }
978   
979  3164 if (lexer.token() == JSONToken.RBRACE) {
980  3164 lexer.nextToken(JSONToken.COMMA);
981  3164 return;
982    }
983    }
984    }
985   
 
986  11 toggle public Object parseArrayWithType(Type collectionType) {
987  11 if (lexer.token() == JSONToken.NULL) {
988  1 lexer.nextToken();
989  1 return null;
990    }
991   
992  10 Type[] actualTypes = ((ParameterizedType) collectionType).getActualTypeArguments();
993   
994  10 if (actualTypes.length != 1) {
995  1 throw new JSONException("not support type " + collectionType);
996    }
997   
998  9 Type actualTypeArgument = actualTypes[0];
999   
1000  9 if (actualTypeArgument instanceof Class) {
1001  1 List<Object> array = new ArrayList<Object>();
1002  1 this.parseArray((Class<?>) actualTypeArgument, array);
1003  1 return array;
1004    }
1005   
1006  8 if (actualTypeArgument instanceof WildcardType) {
1007  3 WildcardType wildcardType = (WildcardType) actualTypeArgument;
1008   
1009    // assert wildcardType.getUpperBounds().length == 1;
1010  3 Type upperBoundType = wildcardType.getUpperBounds()[0];
1011   
1012    // assert upperBoundType instanceof Class;
1013  3 if (Object.class.equals(upperBoundType)) {
1014  2 if (wildcardType.getLowerBounds().length == 0) {
1015    // Collection<?>
1016  1 return parse();
1017    } else {
1018  1 throw new JSONException("not support type : " + collectionType);
1019    }
1020    }
1021   
1022  1 List<Object> array = new ArrayList<Object>();
1023  1 this.parseArray((Class<?>) upperBoundType, array);
1024  1 return array;
1025   
1026    // throw new JSONException("not support type : " +
1027    // collectionType);return parse();
1028    }
1029   
1030  5 if (actualTypeArgument instanceof TypeVariable) {
1031  2 TypeVariable<?> typeVariable = (TypeVariable<?>) actualTypeArgument;
1032  2 Type[] bounds = typeVariable.getBounds();
1033   
1034  2 if (bounds.length != 1) {
1035  1 throw new JSONException("not support : " + typeVariable);
1036    }
1037   
1038  1 Type boundType = bounds[0];
1039  1 if (boundType instanceof Class) {
1040  1 List<Object> array = new ArrayList<Object>();
1041  1 this.parseArray((Class<?>) boundType, array);
1042  1 return array;
1043    }
1044    }
1045   
1046  2 if (actualTypeArgument instanceof ParameterizedType) {
1047  0 ParameterizedType parameterizedType = (ParameterizedType) actualTypeArgument;
1048   
1049  0 List<Object> array = new ArrayList<Object>();
1050  0 Test failure here this.parseArray(parameterizedType, array);
1051  0 return array;
1052    }
1053   
1054  2 throw new JSONException("TODO : " + collectionType);
1055    }
1056   
 
1057  7905 toggle public void acceptType(String typeName) {
1058  7905 JSONLexer lexer = this.lexer;
1059   
1060  7905 lexer.nextTokenWithColon();
1061   
1062  7905 if (lexer.token() != JSONToken.LITERAL_STRING) {
1063  0 throw new JSONException("type not match error");
1064    }
1065   
1066  7905 if (typeName.equals(lexer.stringVal())) {
1067  7905 lexer.nextToken();
1068  7905 if (lexer.token() == JSONToken.COMMA) {
1069  7904 lexer.nextToken();
1070    }
1071    } else {
1072  0 throw new JSONException("type not match error");
1073    }
1074    }
1075   
 
1076  13551 toggle public int getResolveStatus() {
1077  13551 return resolveStatus;
1078    }
1079   
 
1080  22408 toggle public void setResolveStatus(int resolveStatus) {
1081  22408 this.resolveStatus = resolveStatus;
1082    }
1083   
 
1084  3279 toggle public Object getObject(String path) {
1085  31624860 for (int i = 0; i < contextArrayIndex; ++i) {
1086  31624393 if (path.equals(contextArray[i].toString())) {
1087  2812 return contextArray[i].object;
1088    }
1089    }
1090   
1091  467 return null;
1092    }
1093   
 
1094  10168577 toggle @SuppressWarnings("rawtypes")
1095    public void checkListResolve(Collection array) {
1096  10168577 if (resolveStatus == NeedToResolve) {
1097  1401 if (array instanceof List) {
1098  1401 final int index = array.size() - 1;
1099  1401 final List list = (List) array;
1100  1401 ResolveTask task = getLastResolveTask();
1101  1401 task.fieldDeserializer = new ResolveFieldDeserializer(this, list, index);
1102  1401 task.ownerContext = context;
1103  1401 setResolveStatus(DefaultJSONParser.NONE);
1104    } else {
1105  0 ResolveTask task = getLastResolveTask();
1106  0 task.fieldDeserializer = new ResolveFieldDeserializer(array);
1107  0 task.ownerContext = context;
1108  0 setResolveStatus(DefaultJSONParser.NONE);
1109    }
1110    }
1111    }
1112   
 
1113  10142 toggle @SuppressWarnings("rawtypes")
1114    public void checkMapResolve(Map object, Object fieldName) {
1115  10142 if (resolveStatus == NeedToResolve) {
1116  1868 ResolveFieldDeserializer fieldResolver = new ResolveFieldDeserializer(object, fieldName);
1117  1868 ResolveTask task = getLastResolveTask();
1118  1868 task.fieldDeserializer = fieldResolver;
1119  1868 task.ownerContext = context;
1120  1868 setResolveStatus(DefaultJSONParser.NONE);
1121    }
1122    }
1123   
 
1124  60 toggle @SuppressWarnings("rawtypes")
1125    public Object parseObject(final Map object) {
1126  60 Test failure here return parseObject(object, null);
1127    }
1128   
 
1129  47 toggle public JSONObject parseObject() {
1130  47 JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
1131  47 Test failure here Object parsedObject = parseObject(object);
1132   
1133  40 if (parsedObject instanceof JSONObject) {
1134  36 return (JSONObject) parsedObject;
1135    }
1136   
1137  4 if (parsedObject == null) {
1138  3 return null;
1139    }
1140   
1141  1 return new JSONObject((Map) parsedObject);
1142    }
1143   
 
1144  51 toggle @SuppressWarnings("rawtypes")
1145    public final void parseArray(final Collection array) {
1146  51 Test failure here parseArray(array, null);
1147    }
1148   
 
1149  10855 toggle @SuppressWarnings({ "unchecked", "rawtypes" })
1150    public final void parseArray(final Collection array, Object fieldName) {
1151  10855 final JSONLexer lexer = this.lexer;
1152   
1153  10855 if (lexer.token() == JSONToken.SET || lexer.token() == JSONToken.TREE_SET) {
1154  2 lexer.nextToken();
1155    }
1156   
1157  10855 if (lexer.token() != JSONToken.LBRACKET) {
1158  4 throw new JSONException("syntax error, expect [, actual " + JSONToken.name(lexer.token()) + ", pos "
1159    + lexer.pos() + ", fieldName " + fieldName);
1160    }
1161   
1162  10851 Test failure here lexer.nextToken(JSONToken.LITERAL_STRING);
1163   
1164  10850 ParseContext context = this.context;
1165  10850 this.setContext(array, fieldName);
1166  10850 try {
1167  10850 for (int i = 0;; ++i) {
1168  68877 if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
1169  68885 while (lexer.token() == JSONToken.COMMA) {
1170  9 lexer.nextToken();
1171  9 continue;
1172    }
1173    }
1174   
1175  68877 Object value;
1176  68877 switch (lexer.token()) {
1177  22712 case LITERAL_INT:
1178  22712 value = lexer.integerValue();
1179  22712 lexer.nextToken(JSONToken.COMMA);
1180  22712 break;
1181  1046 case LITERAL_FLOAT:
1182  1046 if (lexer.isEnabled(Feature.UseBigDecimal)) {
1183  16 value = lexer.decimalValue(true);
1184    } else {
1185  1030 value = lexer.decimalValue(false);
1186    }
1187  1046 lexer.nextToken(JSONToken.COMMA);
1188  1046 break;
1189  22092 case LITERAL_STRING:
1190  22092 String stringLiteral = lexer.stringVal();
1191  22092 lexer.nextToken(JSONToken.COMMA);
1192   
1193  22092 if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
1194  17857 JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
1195  17857 if (iso8601Lexer.scanISO8601DateIfMatch()) {
1196  44 value = iso8601Lexer.getCalendar().getTime();
1197    } else {
1198  17813 value = stringLiteral;
1199    }
1200  17857 iso8601Lexer.close();
1201    } else {
1202  4235 value = stringLiteral;
1203    }
1204   
1205  22092 break;
1206  7 case TRUE:
1207  7 value = Boolean.TRUE;
1208  7 lexer.nextToken(JSONToken.COMMA);
1209  7 break;
1210  93 case FALSE:
1211  93 value = Boolean.FALSE;
1212  93 lexer.nextToken(JSONToken.COMMA);
1213  93 break;
1214  10267 case LBRACE:
1215  10267 JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
1216  10267 Test failure here value = parseObject(object, i);
1217  10260 break;
1218  897 case LBRACKET:
1219  897 Collection items = new JSONArray();
1220  897 parseArray(items, i);
1221  897 if (lexer.isEnabled(Feature.UseObjectArray)) {
1222  1 value = items.toArray();
1223    } else {
1224  896 value = items;
1225    }
1226  897 break;
1227  917 case NULL:
1228  917 value = null;
1229  917 lexer.nextToken(JSONToken.LITERAL_STRING);
1230  917 break;
1231  1 case UNDEFINED:
1232  1 value = null;
1233  1 lexer.nextToken(JSONToken.LITERAL_STRING);
1234  1 break;
1235  10832 case RBRACKET:
1236  10832 lexer.nextToken(JSONToken.COMMA);
1237  10832 return;
1238  9 case EOF:
1239  9 throw new JSONException("unclosed jsonArray");
1240  4 default:
1241  4 value = parse();
1242  2 break;
1243    }
1244   
1245  58027 array.add(value);
1246  58027 checkListResolve(array);
1247   
1248  58027 if (lexer.token() == JSONToken.COMMA) {
1249  47856 lexer.nextToken(JSONToken.LITERAL_STRING);
1250  47856 continue;
1251    }
1252    }
1253    } finally {
1254  10850 this.setContext(context);
1255    }
1256    }
1257   
 
1258  6166324 toggle public ParseContext getContext() {
1259  6166324 return context;
1260    }
1261   
 
1262  0 toggle public List<ResolveTask> getResolveTaskList() {
1263  0 if (resolveTaskList == null) {
1264  0 resolveTaskList = new ArrayList<ResolveTask>(2);
1265    }
1266  0 return resolveTaskList;
1267    }
1268   
 
1269  3286 toggle public void addResolveTask(ResolveTask task) {
1270  3286 if (resolveTaskList == null) {
1271  44 resolveTaskList = new ArrayList<ResolveTask>(2);
1272    }
1273  3286 resolveTaskList.add(task);
1274    }
1275   
 
1276  3283 toggle public ResolveTask getLastResolveTask() {
1277  3283 return resolveTaskList.get(resolveTaskList.size() - 1);
1278    }
1279   
 
1280  4 toggle public List<ExtraProcessor> getExtraProcessors() {
1281  4 if (extraProcessors == null) {
1282  4 extraProcessors = new ArrayList<ExtraProcessor>(2);
1283    }
1284  4 return extraProcessors;
1285    }
1286   
 
1287  0 toggle public List<ExtraTypeProvider> getExtraTypeProviders() {
1288  0 if (extraTypeProviders == null) {
1289  0 extraTypeProviders = new ArrayList<ExtraTypeProvider>(2);
1290    }
1291  0 return extraTypeProviders;
1292    }
1293   
 
1294  15 toggle public FieldTypeResolver getFieldTypeResolver() {
1295  15 return fieldTypeResolver;
1296    }
1297   
 
1298  1 toggle public void setFieldTypeResolver(FieldTypeResolver fieldTypeResolver) {
1299  1 this.fieldTypeResolver = fieldTypeResolver;
1300    }
1301   
 
1302  18156917 toggle public void setContext(ParseContext context) {
1303  18156917 if (lexer.isEnabled(Feature.DisableCircularReferenceDetect)) {
1304  33 return;
1305    }
1306  18156884 this.context = context;
1307    }
1308   
 
1309  7561 toggle public void popContext() {
1310  7561 if (lexer.isEnabled(Feature.DisableCircularReferenceDetect)) {
1311  0 return;
1312    }
1313   
1314  7561 this.context = this.context.parent;
1315   
1316  7561 if (contextArrayIndex <= 0) {
1317  0 return;
1318    }
1319   
1320  7561 contextArrayIndex--;
1321  7561 contextArray[contextArrayIndex] = null;
1322    }
1323   
 
1324  20055160 toggle public ParseContext setContext(Object object, Object fieldName) {
1325  20055160 if (lexer.isEnabled(Feature.DisableCircularReferenceDetect)) {
1326  3 return null;
1327    }
1328   
1329  20055157 return setContext(this.context, object, fieldName);
1330    }
1331   
 
1332  23149604 toggle public ParseContext setContext(ParseContext parent, Object object, Object fieldName) {
1333  23149604 if (lexer.isEnabled(Feature.DisableCircularReferenceDetect)) {
1334  25 return null;
1335    }
1336   
1337  23149579 this.context = new ParseContext(parent, object, fieldName);
1338  23149579 addContext(this.context);
1339   
1340  23149579 return this.context;
1341    }
1342   
 
1343  23149579 toggle private void addContext(ParseContext context) {
1344  23149579 int i = contextArrayIndex++;
1345  23149579 if (contextArray == null) {
1346  18033699 contextArray = new ParseContext[8];
1347  5115880 } else if (i >= contextArray.length) {
1348  513 int newLen = (contextArray.length * 3) / 2;
1349  513 ParseContext[] newArray = new ParseContext[newLen];
1350  513 System.arraycopy(contextArray, 0, newArray, 0, contextArray.length);
1351  513 contextArray = newArray;
1352    }
1353  23149579 contextArray[i] = context;
1354    }
1355   
 
1356  5034509 toggle public Object parse() {
1357  5034509 Test failure here return parse(null);
1358    }
1359   
 
1360  91 toggle public Object parseKey() {
1361  91 if (lexer.token() == JSONToken.IDENTIFIER) {
1362  20 String value = lexer.stringVal();
1363  20 lexer.nextToken(JSONToken.COMMA);
1364  20 return value;
1365    }
1366  71 return parse(null);
1367    }
1368   
 
1369  5034839 toggle public Object parse(Object fieldName) {
1370  5034839 final JSONLexer lexer = this.lexer;
1371  5034839 switch (lexer.token()) {
1372  6 case SET:
1373  6 lexer.nextToken();
1374  6 HashSet<Object> set = new HashSet<Object>();
1375  6 parseArray(set, fieldName);
1376  5 return set;
1377  2 case TREE_SET:
1378  2 lexer.nextToken();
1379  2 TreeSet<Object> treeSet = new TreeSet<Object>();
1380  2 parseArray(treeSet, fieldName);
1381  1 return treeSet;
1382  123 case LBRACKET:
1383  123 JSONArray array = new JSONArray();
1384  123 Test failure here parseArray(array, fieldName);
1385  107 if (lexer.isEnabled(Feature.UseObjectArray)) {
1386  1 return array.toArray();
1387    }
1388  106 return array;
1389  5005348 case LBRACE:
1390  5005348 JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
1391  5005348 Test failure here return parseObject(object, fieldName);
1392    // case LBRACE: {
1393    // Map<String, Object> map = lexer.isEnabled(Feature.OrderedField)
1394    // ? new LinkedHashMap<String, Object>()
1395    // : new HashMap<String, Object>();
1396    // Object obj = parseObject(map, fieldName);
1397    // if (obj != map) {
1398    // return obj;
1399    // }
1400    // return new JSONObject(map);
1401    // }
1402  20203 case LITERAL_INT:
1403  20203 Number intValue = lexer.integerValue();
1404  20203 lexer.nextToken();
1405  20203 return intValue;
1406  25 case LITERAL_FLOAT:
1407  25 Object value = lexer.decimalValue(lexer.isEnabled(Feature.UseBigDecimal));
1408  24 lexer.nextToken();
1409  24 return value;
1410  6445 case LITERAL_STRING:
1411  6445 String stringLiteral = lexer.stringVal();
1412  6445 lexer.nextToken(JSONToken.COMMA);
1413   
1414  6445 if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
1415  317 JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
1416  317 try {
1417  317 if (iso8601Lexer.scanISO8601DateIfMatch()) {
1418  3 return iso8601Lexer.getCalendar().getTime();
1419    }
1420    } finally {
1421  317 iso8601Lexer.close();
1422    }
1423    }
1424   
1425  6442 return stringLiteral;
1426  224 case NULL:
1427  224 lexer.nextToken();
1428  224 return null;
1429  10 case UNDEFINED:
1430  10 lexer.nextToken();
1431  10 return null;
1432  454 case TRUE:
1433  454 lexer.nextToken();
1434  454 return Boolean.TRUE;
1435  1916 case FALSE:
1436  1916 lexer.nextToken();
1437  1916 return Boolean.FALSE;
1438  12 case NEW:
1439  12 lexer.nextToken(JSONToken.IDENTIFIER);
1440   
1441  12 if (lexer.token() != JSONToken.IDENTIFIER) {
1442  1 throw new JSONException("syntax error");
1443    }
1444  11 lexer.nextToken(JSONToken.LPAREN);
1445   
1446  11 accept(JSONToken.LPAREN);
1447  11 long time = lexer.integerValue().longValue();
1448  11 accept(JSONToken.LITERAL_INT);
1449   
1450  9 accept(JSONToken.RPAREN);
1451   
1452  9 return new Date(time);
1453  34 case EOF:
1454  34 if (lexer.isBlankInput()) {
1455  24 return null;
1456    }
1457  10 throw new JSONException("unterminated json string, " + lexer.info());
1458  2 case HEX:
1459  2 byte[] bytes = lexer.bytesValue();
1460  2 lexer.nextToken();
1461  2 return bytes;
1462  9 case IDENTIFIER:
1463  9 String identifier = lexer.stringVal();
1464  9 if ("NaN".equals(identifier)) {
1465  0 lexer.nextToken();
1466  0 return null;
1467    }
1468  9 throw new JSONException("syntax error, " + lexer.info());
1469  17 case ERROR:
1470  9 default:
1471  26 throw new JSONException("syntax error, " + lexer.info());
1472    }
1473    }
1474   
 
1475  150 toggle public void config(Feature feature, boolean state) {
1476  150 this.lexer.config(feature, state);
1477    }
1478   
 
1479  39 toggle public boolean isEnabled(Feature feature) {
1480  39 return lexer.isEnabled(feature);
1481    }
1482   
 
1483  40516 toggle public JSONLexer getLexer() {
1484  40516 return lexer;
1485    }
1486   
 
1487  514 toggle public final void accept(final int token) {
1488  514 final JSONLexer lexer = this.lexer;
1489  514 if (lexer.token() == token) {
1490  511 Test failure here lexer.nextToken();
1491    } else {
1492  3 throw new JSONException("syntax error, expect " + JSONToken.name(token) + ", actual "
1493    + JSONToken.name(lexer.token()));
1494    }
1495    }
1496   
 
1497  143 toggle public final void accept(final int token, int nextExpectToken) {
1498  143 final JSONLexer lexer = this.lexer;
1499  143 if (lexer.token() == token) {
1500  143 lexer.nextToken(nextExpectToken);
1501    } else {
1502  0 throwException(token);
1503    }
1504    }
1505   
 
1506  0 toggle public void throwException(int token) {
1507  0 throw new JSONException("syntax error, expect " + JSONToken.name(token) + ", actual "
1508    + JSONToken.name(lexer.token()));
1509    }
1510   
 
1511  20055830 toggle public void close() {
1512  20055830 final JSONLexer lexer = this.lexer;
1513   
1514  20055830 try {
1515  20055830 if (lexer.isEnabled(Feature.AutoCloseSource)) {
1516  19052838 if (lexer.token() != JSONToken.EOF) {
1517  3 throw new JSONException("not close json text, token : " + JSONToken.name(lexer.token()));
1518    }
1519    }
1520    } finally {
1521  20055830 lexer.close();
1522    }
1523    }
1524   
 
1525  45 toggle public Object resolveReference(String ref) {
1526  45 if(contextArray == null) {
1527  0 return null;
1528    }
1529  261 for (int i = 0; i < contextArray.length && i < contextArrayIndex; i++) {
1530  254 ParseContext context = contextArray[i];
1531  254 if (context.toString().equals(ref)) {
1532  38 return context.object;
1533    }
1534    }
1535  7 return null;
1536    }
1537   
 
1538  20055660 toggle public void handleResovleTask(Object value) {
1539  20055660 if (resolveTaskList == null) {
1540  20055618 return;
1541    }
1542   
1543  3326 for (int i = 0, size = resolveTaskList.size(); i < size; ++i) {
1544  3284 ResolveTask task = resolveTaskList.get(i);
1545  3284 String ref = task.referenceValue;
1546   
1547  3284 Object object = null;
1548  3284 if (task.ownerContext != null) {
1549  3283 object = task.ownerContext.object;
1550    }
1551   
1552  3284 Object refValue;
1553   
1554  3284 if (ref.startsWith("$")) {
1555  3279 refValue = getObject(ref);
1556  3279 if (refValue == null) {
1557  467 try {
1558  467 refValue = JSONPath.eval(value, ref);
1559    } catch (JSONPathException ex) {
1560    // skip
1561    }
1562    }
1563    } else {
1564  5 refValue = task.context.object;
1565    }
1566   
1567  3284 FieldDeserializer fieldDeser = task.fieldDeserializer;
1568   
1569  3284 if (fieldDeser != null) {
1570  3283 if (refValue != null
1571    && refValue.getClass() == JSONObject.class
1572    && fieldDeser.fieldInfo != null
1573    && !Map.class.isAssignableFrom(fieldDeser.fieldInfo.fieldClass)) {
1574  1 Object root = this.contextArray[0].object;
1575  1 refValue = JSONPath.eval(root, ref);
1576    }
1577   
1578  3283 fieldDeser.setValue(object, refValue);
1579    }
1580    }
1581    }
1582   
 
1583    public static class ResolveTask {
1584   
1585    public final ParseContext context;
1586    public final String referenceValue;
1587    public FieldDeserializer fieldDeserializer;
1588    public ParseContext ownerContext;
1589   
 
1590  3286 toggle public ResolveTask(ParseContext context, String referenceValue){
1591  3286 this.context = context;
1592  3286 this.referenceValue = referenceValue;
1593    }
1594    }
1595   
 
1596  20 toggle public void parseExtra(Object object, String key) {
1597  20 final JSONLexer lexer = this.lexer; // xxx
1598  20 lexer.nextTokenWithColon();
1599  19 Type type = null;
1600   
1601  19 if (extraTypeProviders != null) {
1602  0 for (ExtraTypeProvider extraProvider : extraTypeProviders) {
1603  0 type = extraProvider.getExtraType(object, key);
1604    }
1605    }
1606  19 Object value = type == null //
1607    ? parse() // skip
1608    : parseObject(type);
1609   
1610  19 if (object instanceof ExtraProcessable) {
1611  0 ExtraProcessable extraProcessable = ((ExtraProcessable) object);
1612  0 extraProcessable.processExtra(key, value);
1613  0 return;
1614    }
1615   
1616  19 if (extraProcessors != null) {
1617  1 for (ExtraProcessor process : extraProcessors) {
1618  1 process.processExtra(object, key, value);
1619    }
1620    }
1621   
1622  19 if (resolveStatus == NeedToResolve) {
1623  1 resolveStatus = NONE;
1624    }
1625    }
1626   
 
1627  1 toggle public Object parse(PropertyProcessable object, Object fieldName) {
1628  1 if (lexer.token() != JSONToken.LBRACE) {
1629  0 String msg = "syntax error, expect {, actual " + lexer.tokenName();
1630  0 if (fieldName instanceof String) {
1631  0 msg += ", fieldName ";
1632  0 msg += fieldName;
1633    }
1634  0 msg += ", ";
1635  0 msg += lexer.info();
1636   
1637  0 JSONArray array = new JSONArray();
1638  0 parseArray(array, fieldName);
1639   
1640  0 if (array.size() == 1) {
1641  0 Object first = array.get(0);
1642  0 if (first instanceof JSONObject) {
1643  0 return (JSONObject) first;
1644    }
1645    }
1646   
1647  0 throw new JSONException(msg);
1648    }
1649   
1650  1 ParseContext context = this.context;
1651  1 try {
1652  1 for (int i = 0;;++i) {
1653  3 lexer.skipWhitespace();
1654  3 char ch = lexer.getCurrent();
1655  3 if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
1656  3 while (ch == ',') {
1657  0 lexer.next();
1658  0 lexer.skipWhitespace();
1659  0 ch = lexer.getCurrent();
1660    }
1661    }
1662   
1663  3 String key;
1664  3 if (ch == '"') {
1665  3 key = lexer.scanSymbol(symbolTable, '"');
1666  3 lexer.skipWhitespace();
1667  3 ch = lexer.getCurrent();
1668  3 if (ch != ':') {
1669  0 throw new JSONException("expect ':' at " + lexer.pos());
1670    }
1671  0 } else if (ch == '}') {
1672  0 lexer.next();
1673  0 lexer.resetStringPosition();
1674  0 lexer.nextToken(JSONToken.COMMA);
1675  0 return object;
1676  0 } else if (ch == '\'') {
1677  0 if (!lexer.isEnabled(Feature.AllowSingleQuotes)) {
1678  0 throw new JSONException("syntax error");
1679    }
1680   
1681  0 key = lexer.scanSymbol(symbolTable, '\'');
1682  0 lexer.skipWhitespace();
1683  0 ch = lexer.getCurrent();
1684  0 if (ch != ':') {
1685  0 throw new JSONException("expect ':' at " + lexer.pos());
1686    }
1687    } else {
1688  0 if (!lexer.isEnabled(Feature.AllowUnQuotedFieldNames)) {
1689  0 throw new JSONException("syntax error");
1690    }
1691   
1692  0 key = lexer.scanSymbolUnQuoted(symbolTable);
1693  0 lexer.skipWhitespace();
1694  0 ch = lexer.getCurrent();
1695  0 if (ch != ':') {
1696  0 throw new JSONException("expect ':' at " + lexer.pos() + ", actual " + ch);
1697    }
1698    }
1699   
1700  3 lexer.next();
1701  3 lexer.skipWhitespace();
1702  3 ch = lexer.getCurrent();
1703   
1704  3 lexer.resetStringPosition();
1705   
1706  3 if (key == JSON.DEFAULT_TYPE_KEY && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
1707  0 String typeName = lexer.scanSymbol(symbolTable, '"');
1708   
1709  0 Class<?> clazz = config.checkAutoType(typeName, null, lexer.getFeatures());
1710   
1711  0 if (Map.class.isAssignableFrom(clazz) ) {
1712  0 lexer.nextToken(JSONToken.COMMA);
1713  0 if (lexer.token() == JSONToken.RBRACE) {
1714  0 lexer.nextToken(JSONToken.COMMA);
1715  0 return object;
1716    }
1717  0 continue;
1718    }
1719   
1720  0 ObjectDeserializer deserializer = config.getDeserializer(clazz);
1721   
1722  0 lexer.nextToken(JSONToken.COMMA);
1723   
1724  0 setResolveStatus(DefaultJSONParser.TypeNameRedirect);
1725   
1726  0 if (context != null && !(fieldName instanceof Integer)) {
1727  0 popContext();
1728    }
1729   
1730  0 return (Map) deserializer.deserialze(this, clazz, fieldName);
1731    }
1732   
1733  3 Object value;
1734  3 lexer.nextToken();
1735   
1736  3 if (i != 0) {
1737  2 setContext(context);
1738    }
1739   
1740  3 Type valueType = object.getType(key);
1741   
1742  3 if (lexer.token() == JSONToken.NULL) {
1743  0 value = null;
1744  0 lexer.nextToken();
1745    } else {
1746  3 value = parseObject(valueType, key);
1747    }
1748   
1749  3 object.apply(key, value);
1750   
1751  3 setContext(context, value, key);
1752  3 setContext(context);
1753   
1754  3 final int tok = lexer.token();
1755  3 if (tok == JSONToken.EOF || tok == JSONToken.RBRACKET) {
1756  0 return object;
1757    }
1758   
1759  3 if (tok == JSONToken.RBRACE) {
1760  1 lexer.nextToken();
1761  1 return object;
1762    }
1763    }
1764    } finally {
1765  1 setContext(context);
1766    }
1767    }
1768   
1769    }